using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Framework.Interface;
using UnityEngine;

namespace Framework.StateMechine
{
     public class StateMachine
     {
         private Dictionary<Enum, StateBase> states;
         
         public IApp owner;
         private StateBase current;
         
         public StateMachine(IApp _owner)
         {
             owner = _owner;
             states = new Dictionary<Enum, StateBase>();
         }
     
         public async UniTask Add(Enum id, StateBase state)
         {
             // Debug.Log("AAAAAAAAAA  " + id.ToString() + "  " + (state == null));
             if (!states.ContainsKey(id))
             {
                 // Debug.Log($"[StateMachine] Add   state {id.ToString()} added.");
                 states.Add(id, state);
                 await state.OnCreate(id, this);
             }
             else
             {
                 Debug.LogError($"state {id.ToString()} has been added, do not add again.");
             }
         }
     
         public async UniTask Run(Enum id, StateArgs _args = null)
         {
             if (!states.TryGetValue(id, out current))
             {
                 Debug.LogError($"state {id.ToString()} has not been added.");
             }
             else
             {
                 // Debug.Log($"[StateMachine] Run   state {id.ToString()} as the first one 2 enter.");
                 await current.OnEnter(_args);
             }
         }
     
         public void Update()
         {
             if (current != null)
                 current.OnUpdate();
         }
     
         public async void Change(Enum id, StateArgs _args = null)
         {
             if (!states.TryGetValue(id, out StateBase next))
             {
                 Debug.LogError($"state {id.ToString()} has not been added.");
                 return;
             }
     
             if (current != null)
             {
                 // Debug.Log($"[StateMachine] Change   state {current.Id.ToString()} exit.");
                 await current.OnExit();
             }
     
             current = next;
     
             if (current != null)
             {
                 // Debug.Log($"[StateMachine] Change   state {current.Id.ToString()} enter.");
                 await current.OnEnter(_args);
             }
         }
     }   
}
